#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <mutex>
#include <cassert>

#include "../comm/log.hpp"
#include "../comm/util.hpp"

#include "oj_model.hpp"
#include "oj_view.hpp"

namespace ns_control
{
    using namespace ns_log;
    using namespace ns_util;
    using namespace ns_model;
    using namespace ns_view;

    // 提供服务的主机
    class Machine
    {
    public:
        std::string ip;  // 提供编译服务的ip
        int port;        // 提供编译服务的端口号
        uint64_t load;   // 提供编译服务的负载
        std::mutex *mtx; // 使用锁将load保护起来，但是mutex禁止拷贝，使用指针
    public:
        Machine() : ip(""), port(0), load(0), mtx(nullptr)
        {
        }
        ~Machine() {}
    };

    // 负载均衡模块
    class LoadBlance
    {
    private:
        // 可以给我们提供编译服务的所有的主机
        std::vector<Machine> machines;
        // 每一台主机都有自己的下标，用下标来充当他们各自的id
        // 所有的在线的主机
        std::vector<int> online;
        // 所有的离线主机
        std::vector<int> offline;
        // 锁保证LoadBlance的数据安全
        std::mutex mtx;
    };

    // 核心业务逻辑的控制器
    class Control
    {
    private:
        Model model_; // 提供后台数据
        View view_;   // 提供html渲染功能
    public:
        Control()
        {
        }
        ~Control()
        {
        }

    public:
        // 根据题目数据构建网页
        bool AllQuestion(std::string *html)
        {
            bool ret = true;
            std::vector<struct Question> all;
            if (model_.GetAllQuestions(&all))
            {
                // 获取所有题目信息成功，将所有题目信息构建成网页
                view_.AllExpandHtml(all, html);
            }
            else
            {
                *html = "获取所有题目列表失败!!!";
                ret = false;
            }
            return ret;
        }
        bool Question(const std::string &number, std::string *html)
        {
            bool ret = true;
            struct Question q;
            if (model_.GetOneQuestion(number, &q))
            {
                // 获取指定题目信息成功，将数据构建成网页
                view_.OneExpandHtml(q, html);
            }
            else
            {
                *html = "获取指定题目: " + number + "不存在！！";
                ret = false;
            }
            return ret;
        }
        bool Judge(const std::string in_json, std::string *out_json)
        {
            // 1. 先对in_json进行反序列化，得到题号、代码、输入
            // 2. 重新将用户上传的代码和测试用例拼接形成新的代码
            // 3. 选择负载最低的主机
            // 4. 发起http请求
            // 5. 将编译运行的结果反序列化返回给用户
        }
    };
}